/*
 *  Copyright 2003 by Spectrum Digital Incorporated.
 *  All rights reserved. Property of Spectrum Digital Incorporated.
 */

/*
 *  ======== evmdm642_eeprom.c ========
 *  I2C EEPROM module implementation for DM642 EVM
 */

#include <std.h>
#include <csl.h>
#include <csl_i2c.h>

#include <evmdm642.h>
#include <evmdm642_eeprom.h>

static I2C_Config eepromRcvCfg = {
    0x0000007f, /* I2COAR -    Not used if master */
    0x00000000, /* I2CIER -    Disable interrupts, use polling */
    0x0000001b, /* I2CCLKL -   Low period for 100KHz operation */
    0x0000001b, /* I2CCLKH -   High period for 100KHz operation */
    0x00000002, /* I2CCNT -    Data words per transmission */
    0x00000050, /* I2CSAR -    Slave address */
    0x000044a0, /* I2CMDR -    Mode */
    0x00000019  /* I2CPSC -    Prescale 300MHz to 12MHz */
};

static I2C_Config eepromXmtCfg = {
    0x0000007f, /* I2COAR -    Not used if master */
    0x00000000, /* I2CIER -    Disable interrupts, use polling */
    0x0000001b, /* I2CCLKL -   Low period for 100KHz operation */
    0x0000001b, /* I2CCLKH -   High period for 100KHz operation */
    0x00000002, /* I2CCNT -    Data words per transmission */
    0x00000050, /* I2CSAR -    Slave address */
    0x000046a0, /* I2CMDR -    Mode */
    0x00000019  /* I2CPSC -    Prescale 300MHz to 12MHz */
};

/*
 *  ======== EVMDM642_eeprom_read ========
 *  Read data from an I2C EEPROM
 */
void EVMDM642_EEPROM_read(Uint32 src, Uint32 dst, Uint32 length)
{
    Uint8 *pdst;
    Uint32 i;
    I2C_Config prevI2CCfg;
        
    /* Establish destination pointer */
    pdst = (Uint8 *)dst;

    /* Wait until bus is free */
    while (I2C_bb(EVMDM642_I2C_hI2C));

    /* Save old settings */
    I2C_getConfig(EVMDM642_I2C_hI2C, &prevI2CCfg);
    
    /* Set address using dummy write */
    EVMDM642_EEPROM_write(0, src, 0);

    /* Configure for receive */
    I2C_config(EVMDM642_I2C_hI2C, &eepromRcvCfg);
    EVMDM642_waitusec(1);
  
    /* Generate start condition */
    I2C_start(EVMDM642_I2C_hI2C);

    /* Receive the data */
    for (i = 0; i < length; i++)
    {
        while(!I2C_rrdy(EVMDM642_I2C_hI2C));
        *pdst++ = I2C_readByte(EVMDM642_I2C_hI2C);
    }

    /* Generate stop condition */
    I2C_sendStop(EVMDM642_I2C_hI2C);
    
    /* Need to wait at least 10ms */
    EVMDM642_waitusec(10000);

    /* Wait until bus is free */
    while (I2C_bb(EVMDM642_I2C_hI2C));
        
    /* Reconfigure I2C with old settings */
    I2C_config(EVMDM642_I2C_hI2C, &prevI2CCfg);
}

/*
 *  ======== EVMDM642_eeprom_write ========
 *  Write data to an I2C EEPROM
 */
void EVMDM642_EEPROM_write(Uint32 src, Uint32 dst, Uint32 length)
{
    Uint8 *psrc;
    Uint32 i;
    I2C_Config prevI2CCfg;
        
    /* Establish source pointer */
    psrc = (Uint8 *)src;
    
    /* Wait until bus is free */
    while (I2C_bb(EVMDM642_I2C_hI2C));
    
    /* Clear bus busy */
    I2C_FSETH(EVMDM642_I2C_hI2C, I2CSTR, BB, 1);

    /* Save old settings */
    I2C_getConfig(EVMDM642_I2C_hI2C, &prevI2CCfg);
    
    /* Configure for transmit */
    I2C_config(EVMDM642_I2C_hI2C, &eepromXmtCfg);
    EVMDM642_waitusec(1);
        
    /* Submit the high address byte */
    I2C_writeByte(EVMDM642_I2C_hI2C, (dst & 0xff00) >> 8);
    
    /* Generate start condition */
    I2C_start(EVMDM642_I2C_hI2C);
    
    while(!I2C_xrdy(EVMDM642_I2C_hI2C));

    /* Submit the low address byte */ 
    I2C_writeByte(EVMDM642_I2C_hI2C, dst & 0xff);

    while(!I2C_xrdy(EVMDM642_I2C_hI2C));
    
    /* Transmit the data */
    for (i = 0; i < length; i++)
    {
        I2C_writeByte(EVMDM642_I2C_hI2C, *psrc++);
        while(!I2C_xrdy(EVMDM642_I2C_hI2C));
    }
    
    /* Generate stop condition */
    I2C_sendStop(EVMDM642_I2C_hI2C);

    /* Need to wait at least 10ms */
    EVMDM642_waitusec(10000);

    /* Wait until bus is free */
    while (I2C_bb(EVMDM642_I2C_hI2C));
    
    /* Reconfigure I2C with old settings */
    I2C_config(EVMDM642_I2C_hI2C, &prevI2CCfg);
}
